package com.heiye.blog.ai.strategy.role.impl;

import com.heiye.blog.ai.advisor.impl.RolePromptBuilderAdvisor;
import com.heiye.blog.ai.enums.ResponseCodeEnum;
import com.heiye.blog.ai.enums.RoleNameEnum;
import com.heiye.blog.ai.factory.SoundModelStrategyFactory;
import com.heiye.blog.ai.factory.TextModelStrategyFactory;
import com.heiye.blog.ai.model.dto.AIChatRequest;
import com.heiye.blog.ai.model.dto.TTSRequest;
import com.heiye.blog.ai.model.vo.AIResponse;
import com.heiye.blog.ai.model.vo.AIRoleChatReqVO;
import com.heiye.blog.ai.strategy.role.RoleStrategy;
import com.heiye.blog.ai.strategy.sound.SoundModelStrategy;
import com.heiye.blog.ai.strategy.text.TextModelStrategy;
import com.heiye.blog.framework.common.exception.BizException;
import com.heiye.blog.framework.common.response.Response;
import com.heiye.blog.framework.common.util.JsonUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.Map;
import java.util.Objects;

/**
 * @author: heiye
 * @date: 2025/11/19 下午2:56
 * @version: v1.0.0
 * @description: sayumi 角色策略实现类
 */
@Slf4j
@Component
public class SayumiStrategy implements RoleStrategy {

    @Value("classpath:/prompts/sayumi.st")
    private org.springframework.core.io.Resource templateResource;

    @Resource
    private TextModelStrategyFactory textModelStrategyFactory;

    @Resource
    private SoundModelStrategyFactory soundModelStrategyFactory;

    /**
     * 获取角色名称枚举
     *
     * @return
     */
    @Override
    public RoleNameEnum getRoleNameEnum() {
        return RoleNameEnum.SAYUMI;
    }

    /**
     * 处理流式响应
     *
     * @param aiChatRequest
     * @return
     */
    @Override
    public Flux<AIResponse> handleStreamResponse(AIChatRequest aiChatRequest) {
        // TODO：在这里，我希望可以通过缓存存储的角色信息，判断这里传入的参数是否是正确的。
        //  会判断的参数有：支持的文本模型名称，语言

        // 角色使用的语言
        String language = aiChatRequest.getLanguage();
        // 用户的名称
        String username = aiChatRequest.getUsername();
        // 调用的文本模型名称
        String textModelName = aiChatRequest.getTextModelName();

        // 创建 sayumi 角色提示词模板
        PromptTemplate promptTemplate = new PromptTemplate(templateResource);

        // 填充提示词占位符，转化为 Prompt 提示词对象
        Prompt prompt = promptTemplate.create(
                Map.of("language", language, "username", username));

        // 创建角色提示词构建 advisor
        RolePromptBuilderAdvisor rolePromptBuilderAdvisor = new RolePromptBuilderAdvisor(prompt);

        // 添加角色提示词构建 advisor
        aiChatRequest.advisor(rolePromptBuilderAdvisor);

        // 角色都不支持思考，对于必须思考的模型则对思考过程进行禁用
        aiChatRequest.setThinkEnable(false);
        aiChatRequest.setThinkMaxTokens(0);
        aiChatRequest.setExclude(true);

        // 获取文本模型策略
        TextModelStrategy strategy = textModelStrategyFactory.getStrategy(textModelName);

        // 不支持的文本模型，返回错误信息
        if (Objects.isNull(strategy)) {
            return Flux.error(new BizException(ResponseCodeEnum.TEXT_MODEL_NOT_EXISTED));
        }

        // 调用文本模型策略处理流式响应
        return strategy.handleStreamResponse(aiChatRequest);
    }

    /**
     * 音声生成
     *
     * @param ttsRequest
     * @return
     */
    @Override
    public String soundGeneration(TTSRequest ttsRequest) {
        // TODO：在这里，我希望可以通过缓存存储的角色信息，判断这里传入的参数是否是正确的。
        //  会判断的参数有：支持的声音模型名称、版本、感情, 语言

        // 下面的参数判断，都是因为角色声音模型在该数值的情况下有着很好的效果才设置的
        // 如果 topK 为空，则设置默认值 100
        Integer topK = ttsRequest.getTopK();
        if (Objects.isNull(topK)) {
            ttsRequest.setTopK(100);
        }

        // 获取声音模型策略
        SoundModelStrategy soundModelStrategy =
                soundModelStrategyFactory.getStrategy(ttsRequest.getModel(), ttsRequest.getVersion());

        // 不支持的语音模型，返回错误信息
        if (Objects.isNull(soundModelStrategy)) {
            throw new BizException(ResponseCodeEnum.SOUND_MODEL_NOT_EXISTED);
        }

        // 调用声音模型策略
        return soundModelStrategy.generation(ttsRequest);
    }
}
